home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / epsilon / modal.py < prev    next >
Text File  |  2009-03-13  |  4KB  |  132 lines

  1. # -*- test-case-name: epsilon.test.test_modes -*-
  2.  
  3. import new
  4.  
  5. class ModalMethod(object):
  6.     """A descriptor wrapping multiple implementations of a particular method.
  7.  
  8.     When called on an instance, the implementation used will be
  9.     selected based on an attribute of the instance.  There are no
  10.     unbound ModalMethods at this point.
  11.  
  12.     @ivar name: The name of this method.
  13.     @ivar methods: A mapping of modes to callable objects.
  14.  
  15.     @ivar modeAttribute: The name of the attribute on instances which
  16.     is bound to the instance's current mode.
  17.     """
  18.  
  19.     def __init__(self, name, methods, modeAttribute):
  20.         self.name = name
  21.         self.methods = methods
  22.         self.modeAttribute = modeAttribute
  23.  
  24.     def __get__(self, instance, owner):
  25.         if instance is None:
  26.             raise AttributeError(self.name)
  27.         try:
  28.             mode = getattr(instance, self.modeAttribute)
  29.         except AttributeError:
  30.             raise AttributeError(
  31.                 "Mode attribute %r missing from %r, "
  32.                 "cannot get %r" % (self.modeAttribute, instance, self.name))
  33.  
  34.         try:
  35.             func = self.methods[mode]
  36.         except KeyError:
  37.             raise AttributeError(
  38.                 "Method %r missing from mode %r on %r" % (self.name, mode, instance))
  39.  
  40.         return new.instancemethod(func, instance, owner)
  41.  
  42. class mode(object):
  43.     """
  44.     Base class for mode definitions.  Subclass this in classes of type
  45.     ModalType and provide the implementations of various methods for
  46.     that particular mode as methods of the mode subclass.  The
  47.     subclass should have the same name as the mode it is defining.
  48.     """
  49.  
  50.     # XXX fix the simple, but wrong, __dict__ magic in ModalType.__new__ so
  51.     # that this __enter__ and __exit__ are actually called, maybe we can even
  52.     # do some logging or something.
  53.  
  54.     def __exit__(self):
  55.         """
  56.         The mode has just been exited.
  57.         """
  58.  
  59.     def __enter__(self):
  60.         """
  61.         The mode has just been entered.
  62.         """
  63.  
  64. def _getInheritedAttribute(classname, attrname, bases, attrs):
  65.     try:
  66.         return attrs[attrname]
  67.     except KeyError:
  68.         for base in bases:
  69.             try:
  70.                 return _getInheritedAttribute(classname, attrname,
  71.                                               base.__bases__,
  72.                                               base.__dict__)
  73.             except TypeError:
  74.                 pass
  75.         else:
  76.             raise TypeError('%r does not define required attribute %r' %
  77.                             (classname,
  78.                              attrname))
  79.  
  80.  
  81.  
  82. class ModalType(type):
  83.     """Metaclass for defining modal classes.
  84.  
  85.     @type modeAttribute: C{str}
  86.     @ivar modeAttribute: The attribute to which the current mode is
  87.     bound.  Classes should not define the attribute this names; it
  88.     will be bound automatically to the value of initialMode.
  89.  
  90.     @type initialMode: C{str} (for now)
  91.     @ivar initialMode: The mode in which instances will start.
  92.     """
  93.     def __new__(cls, name, bases, attrs):
  94.         modeAttribute = _getInheritedAttribute(name, 'modeAttribute', bases, attrs)
  95.         initialMode = attrs['initialMode'] = _getInheritedAttribute(name, 'initialMode', bases, attrs)
  96.  
  97.         # Dict mapping names of methods to another dict.  The inner
  98.         # dict maps names of modes to implementations of that method
  99.         # for that mode.
  100.         implementations = {}
  101.  
  102.         keepAttrs = {'mode': initialMode}
  103.         for (k, v) in attrs.iteritems():
  104.             if isinstance(v, type) and issubclass(v, mode):
  105.                 for (methName, methDef) in v.__dict__.iteritems():
  106.                     if methName not in ('__module__', '__file__', '__name__'):
  107.                         implementations.setdefault(methName, {})[k] = methDef
  108.             keepAttrs[k] = v
  109.  
  110.         for (methName, methDefs) in implementations.iteritems():
  111.             keepAttrs[methName] = ModalMethod(methName, methDefs, modeAttribute)
  112.  
  113.         return super(ModalType, cls).__new__(cls, name, bases, keepAttrs)
  114.  
  115. class Modal(object):
  116.  
  117.     __metaclass__ = ModalType
  118.     modeAttribute = 'mode'
  119.     initialMode = 'nil'
  120.  
  121.     class nil(mode):
  122.         def __enter__(self):
  123.             pass
  124.         def __exit__(self):
  125.             pass
  126.  
  127.     def transitionTo(self, stateName):
  128.         self.__exit__()
  129.         self.mode = stateName
  130.         self.__enter__()
  131.  
  132.